import JSSHA from 'jssha';
import log from '../../log';
import * as utils from '../../util';
import {httpsRequestGet} from './index';
import wxConfig from './config';
import * as appSettingCore from '../../api/sys/appsettings/core';

function createNonceStr() {
    return Math.random().toString(36).substr(2, 15);
}
function createTimestamp() {
    const t = new Date().getTime() / 1000;
    return `${parseInt(t, 0)}`;
}

function raw(args) {
    let keys = Object.keys(args);
    keys = keys.sort();
    const newArgs = {};
    keys.forEach((key) => {
        newArgs[key.toLowerCase()] = args[key];
    });

    let string = '';
    for (const k in newArgs) {
        string += `&${k}=${newArgs[k]}`;
    }
    string = string.substr(1);
    return string;
}

/**
 * @synopsis 基础支持的access_token
 *
 * 网页授权access_token 是一次性的，而基础支持的access_token的是有时间限制的
 *
 * @returns 基础支持的access_token
 */
function getAccessToken() {
    return utils.resolve().then(() => {
        return appSettingCore.find({type: 'wx'}).then(r => {
            r = r[0];
            const accessTokenJson = JSON.parse(r.content);
            log.info('=============== 数据库 wx accessTokenJson:', accessTokenJson);
            //判断是否过期
            if (new Date().getTime() < parseInt(accessTokenJson.accessToken.expires_time, 0)) {
                //调用校验接口，校验access_token是否有效

                return accessTokenJson.accessToken.access_token;
            }
            const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${wxConfig.appID}&secret=${wxConfig.appScrect}`;
            return httpsRequestGet(url).then((data) => {
                log.info('token return:', data);
                data = JSON.parse(data);
                if (data.errcode > 0) {
                    throw data;
                }
                accessTokenJson.accessToken.access_token = data.access_token;
                accessTokenJson.accessToken.expires_time = new Date().getTime() + (data.expires_in * 1000);
                r.content = JSON.stringify(accessTokenJson);
                appSettingCore.edit(r);
                return accessTokenJson.accessToken.access_token;
            });
        });
    }).catch(err => {
        log.error('jssdk getAccessToken is err----', err);
        return err;
    });
}

function getJsApiTicket() {
    return utils.resolve().then(() => {
        return appSettingCore.find({type: 'wx'}).then(r => {
            r = r[0];
            const accessTokenJson = JSON.parse(r.content);
            log.info('=============== 数据库 accessTokenJson:', accessTokenJson);
            //判断是否过期
            if (new Date().getTime() < parseInt(accessTokenJson.jsApiTicket.expires_time, 0)) {
                return accessTokenJson.jsApiTicket.ticket;
            }
            const url = `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${accessTokenJson.accessToken.access_token}&type=jsapi`;
            return httpsRequestGet(url).then((data) => {
                log.info('token return:', data);
                data = JSON.parse(data);
                if (data.errcode) {
                    throw data;
                }
                accessTokenJson.jsApiTicket.ticket = data.ticket;
                accessTokenJson.jsApiTicket.expires_time = new Date().getTime() + (data.expires_in * 1000);
                r.content = JSON.stringify(accessTokenJson);
                appSettingCore.edit(r);
                return accessTokenJson.jsApiTicket.ticket;
            });
        });
    }).catch(err => {
        log.error('jssdk getJsApiTicket is err----', err);
        return err;
    });
}

/**
 * @synopsis 签名算法
 *
 * //@param jsapi_ticket 用于签名的 jsapi_ticket
 * @param query: url 用于签名的 url ，注意必须动态获取，不能 hardcode
 *
 * @returns
 */
function sign(query) {
    return utils.resolve().then(() => {
        let {url} = query;
        log.info('分享页面传参xxxxxxxx: url:', url);
        //url = url.substr(0, url.indexOf('#'));
        url = url.split('#')[0];
        return getAccessToken().then(() => {
            return getJsApiTicket().then(r => {
                const ret = {
                    jsapi_ticket: r,
                    nonceStr: createNonceStr(),
                    timestamp: createTimestamp(),
                    url
                };
                const string = raw(ret);
                log.info('============ ret:', ret);
                log.info('============ string:', string);
                const shaObj = new JSSHA(string, 'TEXT');
                ret.signature = shaObj.getHash('SHA-1', 'HEX');
                return ret;
            });
        });
    }).catch(err => {
        log.error('jssdk sign is err----', err);
        return err;
    });
}

/**
 * @synopsis 签名算法
 *
 * //@param jsapi_ticket 用于签名的 jsapi_ticket
 * @param query: url 用于签名的 url ，注意必须动态获取，不能 hardcode
 *
 * @returns
 */
function checkSign(query) {
    return utils.resolve().then(() => {
        log.info('quyer:', query);
        const {signature, timestamp, nonce, echostr} = query;
        const ret = {
            token: 'idacheng',
            timestamp,
            nonce
        };
        const string = raw(ret);
        const shaObj = new JSSHA(string, 'TEXT');
        const mySignature = shaObj.getHash('SHA-1', 'HEX');
        log.info('============ mySignature:', mySignature);
        if (signature === mySignature) {
            return echostr;
        }
        return echostr;
    }).catch(err => {
        log.error('jssdk sign is err----', err);
        return err;
    });
}
export {sign, checkSign};
